package com.ruoyi.task;


import com.alibaba.fastjson.JSONObject;
import com.ruoyi.domain.AdvOrders;
import com.ruoyi.enums.OrderStatusEnum;
import com.ruoyi.mapper.AdvOrdersMapper;
import com.ruoyi.service.WxAppService;
import com.ruoyi.service.WxPayService;
import com.ruoyi.utils.SimpleResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Slf4j
@Component
public class WxPayTask {
    @Value("${wxapp.api-token-path}")
    private String TOKEN_PATH;

    @Value("${wxapp.app-token-file-name}")
    private String TOKEN_FILE_NAME;

    @Autowired
    private AdvOrdersMapper advOrdersMapper;

    @Resource
    private WxPayService wxPayService;

    @Resource
    private WxAppService wxAppService;

    /**
     * 获取小程序的token(每两个小时执行一次)
     * @throws IOException
     */
//    @Scheduled(cron = "0 0 0/2 * * ?")
    public void getAppAccessToken() throws IOException {
        File f = new File(TOKEN_PATH);
        if(!f.exists()) {
            f.mkdirs();
        }
        System.out.println("准备获取小程序token");
        Map<String, String> accessToken = wxAppService.getAccessToken();
        if(!Objects.isNull(accessToken)) {
            String jsonString = JSONObject.toJSONString(accessToken);
            File file = new File(TOKEN_PATH + TOKEN_FILE_NAME);
            FileOutputStream outputStream = new FileOutputStream(file);
            outputStream.write(jsonString.getBytes(StandardCharsets.UTF_8));
            outputStream.close();
            System.out.println("写入数据完成 ====> " + TOKEN_PATH + TOKEN_FILE_NAME);
        } else {
            File file = new File(TOKEN_PATH + TOKEN_FILE_NAME);
            FileOutputStream outputStream = new FileOutputStream(file);
            outputStream.write("获取token发生错误".getBytes(StandardCharsets.UTF_8));
            System.out.println("定时器获取token失败");
            outputStream.close();
        }
    }


    /**
     *  秒 分 时 日 月 周
     *  以秒为例
     *  *：每秒都执行
     *  1-3：从第一秒开始执行，到第三秒结束执行
     *  0/3：从第三秒开始，每隔3秒执行一次
     *  1，2，3：在指定的第1，2，3秒开始执行
     * ?不指定
     *  日和周不能同时指定，指定其中一个，则另一个设置为?
     *
     * 从第0秒开始每隔30秒执行一次，查询创建超过5分钟，并且未支付的订单
     */
    /**
     * 核实支付状态的定时器
     * @throws IOException
     */
//    @Scheduled(cron = "0/30 * * * * ?")
    public void orderConfirm() throws IOException {

//        System.out.println("查询已支付的订单定时任务被执行.........");

        Instant instant = Instant.now().minus(Duration.ofMinutes(1));
        List<AdvOrders> orderInfoList = advOrdersMapper.getNoPayOrderByDuration(instant);  //设置时间

        for (AdvOrders orderInfo : orderInfoList) {
            String orderNo = orderInfo.getOrdersno();
//            System.out.println("超时订单---》"+orderNo);
            //核实订单状态：调用微信支付接口
            wxPayService.checkOrderStatus(orderNo);

        }

    }

    /**
     * 从第0分钟开始每五分钟查询一次订单状态并作出改变，
     * 如果有超7天未收货，自动改变订单状态为已收货
     * @throws IOException
     */
//    @Scheduled(cron = "0 0/5 * * * ?")
    public void orderStatusUpdateReceive() throws IOException {
//        System.out.println("每5分钟执行一次被执行.........");

        // 当前时间减去7天
        LocalDateTime sevenDaysAgo = LocalDateTime.now().minusDays(7);

        // 查询状态为已发货且发货日期超过7天的订单
        List<AdvOrders> ordersToUpdate = advOrdersMapper.findOrdersByStatusAndSendDateBefore(OrderStatusEnum.Send_Goods.getType(), sevenDaysAgo);

        for (AdvOrders advOrders : ordersToUpdate) {
            // 更新订单状态为已收货
            advOrdersMapper.updateOrderStatusAndConfirmDate(advOrders.getAdvOrdersId(), OrderStatusEnum.Receive_Goods.getType(), LocalDateTime.now());
        }
    }

    /**
     * 从第0分钟开始每五分钟查询一次订单状态并作出改变，
     * 如果有已收货超过30天，自动改变订单状态为已完成
     * @throws IOException
     */
//    @Scheduled(cron = "0 0/5 * * * ?")
    public void orderStatusUpdateOver() throws IOException {
//        System.out.println("每5分钟执行一次被执行.........");

        // 当前时间减去30天
        LocalDateTime dateTime = LocalDateTime.now().minusDays(30);

        // 查询状态为已发货且发货日期超过30天的订单
        List<AdvOrders> ordersToUpdate = advOrdersMapper.findOrdersByStatusAndSendDateBefore(OrderStatusEnum.Receive_Goods.getType(), dateTime);

        for (AdvOrders advOrders : ordersToUpdate) {
            // 更新订单状态为已完成
            advOrdersMapper.updateOrderStatusAndConfirmDate(advOrders.getAdvOrdersId(), OrderStatusEnum.ORDER_OVER.getType(), LocalDateTime.now());
        }
    }

}
